﻿using System;
using System.Collections.Generic;

namespace YArchitech.Plumbing
{
	public class GeothermalSystemCalc
	{
		public GeothermalSystemCalc(OptionData optionData, InBuildSystem inBuildSystem, bool beDesign)
		{
			this.option = new OptionData(optionData);
			this.buildSystem = new InBuildSystem(inBuildSystem);
			this.averageTemper = (this.option.TemperReturn + this.option.TemperSupply) / 2.0;
			this.beFirst = beDesign;
			this.waterDensity = GHCalcMethods.GetWaterDensity(this.averageTemper);
			this.waterVis = GHCalcMethods.GetKinematicViscosity(this.averageTemper);
			this.densitySupply = GHCalcMethods.GetWaterDensity(this.option.TemperSupply);
			this.densityReturn = GHCalcMethods.GetWaterDensity(this.option.TemperReturn);
		}

		public void DesignCalc()
		{
			this.CalcDiameterPerPipe();
			this.CalTCValvePress();
			this.CalControlValveCPress();
			this.CalcControlValveAPress();
			double num = this.GetMaxTotalResistance();
			num *= 1.1;
			FloorSystem floorSystem = this.buildSystem.SrpSystems[this.IndexLg].FloorSystems[this.IndexLc];
			num += floorSystem.IndoorSystems[this.IndexHn].CirclePipes[this.IndexHl].ResistTcValve;
			if (this.option.DPValvePosition == 1 || this.option.DPValvePosition == 2)
			{
				num += floorSystem.IndoorSystems[this.IndexHn].DPressCapital;
			}
			this.buildSystem.TotalResistance = num;
			this.CalcUnbalanceRate();
		}

		public void CalcDiameterPerPipe()
		{
			foreach (HYPipeData hyPipe in this.buildSystem.SupplyTmPipe)
			{
				this.CalcPipeDiameter(hyPipe, this.waterDensity, this.waterVis);
			}
			foreach (HYPipeData hyPipe2 in this.buildSystem.ReturnTmPipe)
			{
				this.CalcPipeDiameter(hyPipe2, this.waterDensity, this.waterVis);
			}
			foreach (ShareRPipeSystem shareRPipeSystem in this.buildSystem.SrpSystems)
			{
				foreach (HYPipeData hyPipe3 in shareRPipeSystem.SupplyPipes)
				{
					this.CalcPipeDiameter(hyPipe3, this.waterDensity, this.waterVis);
				}
				foreach (HYPipeData hyPipe4 in shareRPipeSystem.ReturnPipes)
				{
					this.CalcPipeDiameter(hyPipe4, this.waterDensity, this.waterVis);
				}
				IEnumerable<FloorSystem> floorSystems = shareRPipeSystem.FloorSystems;
				int num = 0;
				foreach (FloorSystem floorSystem in floorSystems)
				{
					foreach (IndoorSystem indoorSystem in floorSystem.IndoorSystems)
					{
						double pressDynamic = shareRPipeSystem.SupplyPipes[num].PressDynamic;
						indoorSystem.DPressDevise = pressDynamic * this.option.ResistanceLocal + this.option.Resistance * 1000.0;
						if (indoorSystem.CircleNum > 1)
						{
							this.CalcPlasticPipeDiameter(indoorSystem.SupplyMPipe, this.waterDensity, this.waterVis, false);
							this.CalcPlasticPipeDiameter(indoorSystem.ReturnMPipe, this.waterDensity, this.waterVis, false);
						}
						foreach (CirclePipe circlePipe in indoorSystem.CirclePipes)
						{
							this.CalcPlasticPipeDiameter(circlePipe.PipeData, this.waterDensity, this.waterVis, true);
						}
					}
					num++;
				}
			}
		}

		private void CalTCValvePress()
		{
			double num = 0.0;
			double num2 = this.option.DiffTCValve * 1000.0;
			double num3 = this.option.DiffTCValve * 1000.0;
			double num4 = this.GetMaxResistance();
			num4 += num3;
			for (int i = 0; i < this.buildSystem.RiserPipeNum; i++)
			{
				double num5 = num4;
				for (int j = 0; j <= i; j++)
				{
					num5 -= this.buildSystem.SupplyTmPipe[j].Resistance;
				}
				if (this.buildSystem.PipeConnForm == 1)
				{
					for (int j = this.buildSystem.ReturnTmPipe.Count - 1; j >= i; j--)
					{
						num5 -= this.buildSystem.ReturnTmPipe[j].Resistance;
					}
				}
				else
				{
					for (int j = 0; j <= i; j++)
					{
						num5 -= this.buildSystem.ReturnTmPipe[j].Resistance;
					}
				}
				ShareRPipeSystem shareRPipeSystem = this.buildSystem.SrpSystems[i];
				for (int k = 0; k < shareRPipeSystem.FloorSystems.Count; k++)
				{
					double num6 = num5;
					for (int j = 0; j <= k; j++)
					{
						num6 -= shareRPipeSystem.SupplyPipes[k].Resistance;
					}
					if (shareRPipeSystem.PipeConnForm == 1)
					{
						for (int j = shareRPipeSystem.ReturnPipes.Count - 1; j >= i; j--)
						{
							num6 -= shareRPipeSystem.ReturnPipes[j].Resistance;
						}
					}
					else
					{
						for (int j = 0; j <= k; j++)
						{
							num6 -= shareRPipeSystem.ReturnPipes[k].Resistance;
						}
					}
					double num7 = 6.540327 * this.GetFloorHeight(k) * (this.densityReturn - this.densitySupply);
					num6 += num7;
					FloorSystem floorSystem = shareRPipeSystem.FloorSystems[k];
					for (int l = 0; l < floorSystem.IndoorSystems.Count; l++)
					{
						IndoorSystem indoorSystem = floorSystem.IndoorSystems[l];
						for (int m = 0; m < indoorSystem.CircleNum; m++)
						{
							double num8 = num6;
							num8 -= indoorSystem.DPressDevise;
							if (indoorSystem.CircleNum > 1)
							{
								num8 -= indoorSystem.SupplyMPipe.Resistance;
								num8 -= indoorSystem.ReturnMPipe.Resistance;
							}
							CirclePipe circlePipe = indoorSystem.CirclePipes[m];
							num8 -= circlePipe.PipeData.Resistance;
							circlePipe.ResistTcValve = num8;
							if (num8 < num2)
							{
								num2 = num8;
								this.index_lg = i;
								this.index_lc = k;
								this.index_hn = l;
								this.index_hl = m;
							}
						}
					}
				}
			}
			if (num2 < num3)
			{
				num = num3 - num2;
				foreach (ShareRPipeSystem shareRPipeSystem2 in this.buildSystem.SrpSystems)
				{
					foreach (FloorSystem floorSystem2 in shareRPipeSystem2.FloorSystems)
					{
						foreach (IndoorSystem indoorSystem2 in floorSystem2.IndoorSystems)
						{
							foreach (CirclePipe circlePipe2 in indoorSystem2.CirclePipes)
							{
								circlePipe2.ResistTcValve += num;
							}
						}
					}
				}
			}
		}

		private void CalControlValveCPress()
		{
			for (int i = 0; i < this.buildSystem.RiserPipeNum; i++)
			{
				ShareRPipeSystem shareRPipeSystem = this.buildSystem.SrpSystems[i];
				for (int j = 0; j < shareRPipeSystem.FloorSystems.Count; j++)
				{
					FloorSystem floorSystem = shareRPipeSystem.FloorSystems[j];
					double num;
					for (int k = 0; k < floorSystem.IndoorNum; k++)
					{
						IndoorSystem indoorSystem = floorSystem.IndoorSystems[k];
						for (int l = 0; l < indoorSystem.CircleNum; l++)
						{
							num = 0.0;
							CirclePipe circlePipe = indoorSystem.CirclePipes[l];
							num += circlePipe.PipeData.Resistance;
							num += circlePipe.ResistTcValve;
							num += indoorSystem.DPressCapital;
							indoorSystem.DPressControl = num;
						}
					}
					num = 0.0;
					num += shareRPipeSystem.SupplyPipes[0].Resistance;
					if (shareRPipeSystem.PipeConnForm == 1)
					{
						for (int m = 0; m < shareRPipeSystem.ReturnPipes.Count; m++)
						{
							num += shareRPipeSystem.ReturnPipes[m].Resistance;
						}
					}
					else
					{
						num += shareRPipeSystem.ReturnPipes[0].Resistance;
					}
					num += shareRPipeSystem.FloorSystems[0].IndoorSystems[0].DPressControl;
					shareRPipeSystem.DPressControl = num;
				}
			}
		}

		private void CalcControlValveAPress()
		{
			double num = 0.0;
			if (this.option.DPValvePosition != 3)
			{
				num = this.option.DiffDPValve * 1000.0;
			}
			double num2 = num;
			double num3 = this.GetMaxTotalResistance();
			num3 += this.option.DiffTCValve * 1000.0;
			num3 += num;
			for (int i = 0; i < this.buildSystem.RiserPipeNum; i++)
			{
				double num4 = num3;
				for (int j = 0; j <= i; j++)
				{
					num4 -= this.buildSystem.SupplyTmPipe[i].Resistance;
				}
				if (this.buildSystem.PipeConnForm == 1)
				{
					for (int j = this.buildSystem.RiserPipeNum - 1; j >= i; j--)
					{
						num4 -= this.buildSystem.ReturnTmPipe[i].Resistance;
					}
				}
				else
				{
					for (int j = 0; j <= i; j++)
					{
						num4 -= this.buildSystem.ReturnTmPipe[i].Resistance;
					}
				}
				ShareRPipeSystem shareRPipeSystem = this.buildSystem.SrpSystems[i];
				shareRPipeSystem.DPressCapital = num4;
				if (this.option.DPValvePosition == 2 && num4 < num)
				{
					num = num4;
				}
				for (int k = 0; k < shareRPipeSystem.FloorSystems.Count; k++)
				{
					double num5 = num4;
					for (int j = 0; j <= k; j++)
					{
						num5 -= shareRPipeSystem.SupplyPipes[k].Resistance;
					}
					if (shareRPipeSystem.PipeConnForm == 1)
					{
						for (int j = shareRPipeSystem.ReturnPipes.Count - 1; j >= k; j--)
						{
							num5 -= shareRPipeSystem.ReturnPipes[k].Resistance;
						}
					}
					else
					{
						for (int j = 0; j <= k; j++)
						{
							num5 -= shareRPipeSystem.ReturnPipes[k].Resistance;
						}
					}
					FloorSystem floorSystem = shareRPipeSystem.FloorSystems[k];
					double num6 = 6.540327 * this.GetFloorHeight(k) * (this.densityReturn - this.densitySupply);
					num5 += num6;
					for (int l = 0; l < floorSystem.IndoorNum; l++)
					{
						floorSystem.IndoorSystems[l].DPressCapital = num5;
						if (this.option.DPValvePosition == 1 && num4 < num)
						{
							num = num4;
						}
					}
				}
			}
			if (num < num2)
			{
				double num7 = num2 - num;
				for (int i = 0; i < this.buildSystem.RiserPipeNum; i++)
				{
					ShareRPipeSystem shareRPipeSystem2 = this.buildSystem.SrpSystems[i];
					if (this.option.DPValvePosition == 2)
					{
						shareRPipeSystem2.DPressCapital += num7;
					}
					for (int k = 0; k < shareRPipeSystem2.FloorSystems.Count; k++)
					{
						FloorSystem floorSystem2 = shareRPipeSystem2.FloorSystems[k];
						for (int l = 0; l < floorSystem2.IndoorNum; l++)
						{
							IndoorSystem indoorSystem = floorSystem2.IndoorSystems[l];
							if (this.option.DPValvePosition == 1)
							{
								indoorSystem.DPressCapital += num7;
							}
						}
					}
				}
			}
		}

		private void CalcUnbalanceRate()
		{
			this.buildSystem.PressCapital = 0.0;
			this.buildSystem.PressActual = 0.0;
			this.buildSystem.RateUnbalance = 0.0;
			for (int i = 0; i < this.buildSystem.RiserPipeNum; i++)
			{
				ShareRPipeSystem shareRPipeSystem = this.buildSystem.SrpSystems[i];
				shareRPipeSystem.PressActual = 0.0;
				for (int j = 0; j < shareRPipeSystem.FloorSystems.Count; j++)
				{
					FloorSystem floorSystem = shareRPipeSystem.FloorSystems[j];
					floorSystem.PressActual = 0.0;
					for (int k = 0; k < floorSystem.IndoorNum; k++)
					{
						IndoorSystem indoorSystem = floorSystem.IndoorSystems[k];
						indoorSystem.PressActual = 0.0;
						for (int l = 0; l < indoorSystem.CircleNum; l++)
						{
							CirclePipe circlePipe = indoorSystem.CirclePipes[l];
							circlePipe.PressActual = circlePipe.PipeData.Resistance;
							if (indoorSystem.PressActual < circlePipe.PressActual)
							{
								indoorSystem.PressActual = circlePipe.PressActual;
							}
						}
						for (int l = 0; l < indoorSystem.CircleNum; l++)
						{
							CirclePipe circlePipe2 = indoorSystem.CirclePipes[l];
							circlePipe2.RateUnbalance = 100.0 * (indoorSystem.PressActual - circlePipe2.PressActual) / indoorSystem.PressActual;
						}
						if (indoorSystem.CircleNum > 1)
						{
							indoorSystem.PressActual += indoorSystem.SupplyMPipe.Resistance;
							indoorSystem.PressActual += indoorSystem.ReturnMPipe.Resistance;
						}
						if (floorSystem.PressActual < indoorSystem.PressActual)
						{
							floorSystem.PressActual = indoorSystem.PressActual;
						}
					}
					for (int k = 0; k < floorSystem.IndoorNum; k++)
					{
						IndoorSystem indoorSystem2 = floorSystem.IndoorSystems[k];
						indoorSystem2.RateUnbalance = 100.0 * (floorSystem.PressActual - indoorSystem2.PressActual) / floorSystem.PressActual;
					}
				}
				for (int j = 0; j < shareRPipeSystem.FloorSystems.Count; j++)
				{
					FloorSystem floorSystem2 = shareRPipeSystem.FloorSystems[j];
					for (int m = 0; m <= j; m++)
					{
						floorSystem2.PressActual += shareRPipeSystem.SupplyPipes[m].Resistance;
					}
					if (shareRPipeSystem.PipeConnForm == 1)
					{
						for (int m = j; m < shareRPipeSystem.FloorSystems.Count; m++)
						{
							floorSystem2.PressActual += shareRPipeSystem.ReturnPipes[m].Resistance;
						}
					}
					else
					{
						for (int m = 0; m <= j; m++)
						{
							floorSystem2.PressActual += shareRPipeSystem.ReturnPipes[m].Resistance;
						}
					}
					if (shareRPipeSystem.PressActual < floorSystem2.PressActual)
					{
						shareRPipeSystem.PressActual = floorSystem2.PressActual;
					}
				}
				for (int j = 0; j < shareRPipeSystem.FloorSystems.Count; j++)
				{
					FloorSystem floorSystem3 = shareRPipeSystem.FloorSystems[j];
					floorSystem3.RateUnbalance = 100.0 * (shareRPipeSystem.PressActual - floorSystem3.PressActual) / shareRPipeSystem.PressActual;
				}
			}
			for (int i = 0; i < this.buildSystem.RiserPipeNum; i++)
			{
				ShareRPipeSystem shareRPipeSystem2 = this.buildSystem.SrpSystems[i];
				for (int m = 0; m <= i; m++)
				{
					shareRPipeSystem2.PressActual += this.buildSystem.SupplyTmPipe[m].Resistance;
				}
				if (this.buildSystem.PipeConnForm == 1)
				{
					for (int m = i; m < this.buildSystem.ReturnTmPipe.Count; m++)
					{
						shareRPipeSystem2.PressActual += this.buildSystem.ReturnTmPipe[m].Resistance;
					}
				}
				else
				{
					for (int m = 0; m <= i; m++)
					{
						shareRPipeSystem2.PressActual += this.buildSystem.ReturnTmPipe[m].Resistance;
					}
				}
				if (this.buildSystem.PressActual < shareRPipeSystem2.PressActual)
				{
					this.buildSystem.PressActual = shareRPipeSystem2.PressActual;
				}
			}
			for (int i = 0; i < this.buildSystem.RiserPipeNum; i++)
			{
				ShareRPipeSystem shareRPipeSystem3 = this.buildSystem.SrpSystems[i];
				shareRPipeSystem3.RateUnbalance = 100.0 * (this.buildSystem.PressActual - shareRPipeSystem3.PressActual) / this.buildSystem.PressActual;
			}
		}

		private double GetFloorHeight(int floorNum)
		{
			double num = 0.0;
			for (int i = 0; i < floorNum; i++)
			{
				if (i == 0)
				{
					num += 0.5;
				}
				else
				{
					num += this.option.FloorList[i].Height;
				}
			}
			return num;
		}

		private double GetMaxResistance()
		{
			double num = 0.0;
			foreach (HYPipeData hypipeData in this.buildSystem.SupplyTmPipe)
			{
				num += hypipeData.Resistance;
			}
			if (this.buildSystem.PipeConnForm == 1)
			{
				num += this.buildSystem.ReturnTmPipe[this.buildSystem.ReturnTmPipe.Count - 1].Resistance;
			}
			else
			{
				foreach (HYPipeData hypipeData2 in this.buildSystem.ReturnTmPipe)
				{
					num += hypipeData2.Resistance;
				}
			}
			ShareRPipeSystem shareRPipeSystem = this.buildSystem.SrpSystems[this.buildSystem.ReturnTmPipe.Count - 1];
			num += shareRPipeSystem.SupplyPipes[0].Resistance;
			if (shareRPipeSystem.PipeConnForm == 1)
			{
				IEnumerator<HYPipeData> enumerator = shareRPipeSystem.ReturnPipes.GetEnumerator();
				{
					while (enumerator.MoveNext())
					{
						HYPipeData hypipeData3 = enumerator.Current;
						num += hypipeData3.Resistance;
					}
					goto IL_14D;
				}
			}
			num += shareRPipeSystem.ReturnPipes[0].Resistance;
			IL_14D:
			IndoorSystem indoorSystem = shareRPipeSystem.FloorSystems[0].IndoorSystems[0];
			num += indoorSystem.DPressDevise;
			if (indoorSystem.CircleNum > 1)
			{
				num += indoorSystem.SupplyMPipe.Resistance;
				num += indoorSystem.ReturnMPipe.Resistance;
			}
			CirclePipe circlePipe = indoorSystem.CirclePipes[0];
			num += circlePipe.PipeData.Resistance;
			return num;
		}

		private double GetMaxTotalResistance()
		{
			double num = 0.0;
			for (int i = 0; i <= this.IndexLg; i++)
			{
				num += this.buildSystem.SupplyTmPipe[i].Resistance;
			}
			if (this.buildSystem.PipeConnForm == 1)
			{
				for (int j = this.buildSystem.RiserPipeNum - 1; j >= this.IndexLg; j--)
				{
					num += this.buildSystem.ReturnTmPipe[j].Resistance;
				}
			}
			else
			{
				for (int k = 0; k <= this.IndexLg; k++)
				{
					num += this.buildSystem.ReturnTmPipe[k].Resistance;
				}
			}
			ShareRPipeSystem shareRPipeSystem = this.buildSystem.SrpSystems[this.index_lg];
			for (int l = 0; l <= this.IndexLc; l++)
			{
				num += shareRPipeSystem.SupplyPipes[l].Resistance;
			}
			if (shareRPipeSystem.PipeConnForm == 1)
			{
				for (int m = shareRPipeSystem.ReturnPipes.Count - 1; m >= this.IndexLc; m--)
				{
					num += shareRPipeSystem.ReturnPipes[m].Resistance;
				}
			}
			else
			{
				for (int n = 0; n <= this.IndexLc; n++)
				{
					num += shareRPipeSystem.ReturnPipes[n].Resistance;
				}
			}
			IndoorSystem indoorSystem = shareRPipeSystem.FloorSystems[this.IndexLc].IndoorSystems[this.IndexHn];
			num += indoorSystem.DPressDevise;
			if (indoorSystem.CircleNum > 1)
			{
				num += indoorSystem.SupplyMPipe.Resistance;
				num += indoorSystem.ReturnMPipe.Resistance;
			}
			return num + indoorSystem.CirclePipes[this.IndexHl].PipeData.Resistance;
		}

		private void CalcPipeDiameter(HYPipeData hyPipe, double waterDensity, double waterVis)
		{
			if (this.beFirst)
			{
				hyPipe.Diameter = GHCalcMethods.GetDN(hyPipe.Flow, 45.0, waterVis, waterDensity, 0.2);
			}
			hyPipe.Speed = GHCalcMethods.GetSpeed(hyPipe.Flow, hyPipe.Diameter, waterDensity);
			double frictionCoeffic = GHCalcMethods.GetFrictionCoeffic(hyPipe.Speed, hyPipe.Diameter, 0.2, waterVis);
			hyPipe.ResistanceFrict = GHCalcMethods.GetRm(hyPipe.Flow, hyPipe.Diameter, frictionCoeffic, waterDensity);
			hyPipe.PressDynamic = waterDensity * Math.Pow(hyPipe.Speed, 2.0) / 2.0;
			hyPipe.DragForce = hyPipe.PressDynamic * hyPipe.Length;
			hyPipe.ResistanceLocal = hyPipe.PressDynamic * hyPipe.ResCoefLocal;
			hyPipe.Resistance = hyPipe.DragForce + hyPipe.ResistanceLocal;
		}

		private void CalcPlasticPipeDiameter(HYPipeData hyPipe, double waterDensity, double waterVis, bool beCircle)
		{
			if (this.beFirst)
			{
				hyPipe.Diameter = GHCalcMethods.GetXPAPDN(hyPipe.Flow, waterDensity);
				hyPipe.OutDiameter = GHCalcMethods.GetXPAPWJB(hyPipe.Diameter).ToString();
			}
			hyPipe.Speed = GHCalcMethods.GetXPAPV(hyPipe.Flow, (double)hyPipe.Diameter, waterDensity);
			hyPipe.ResistanceFrict = GHCalcMethods.GetXPAPR(hyPipe.Flow, (double)hyPipe.Diameter, waterDensity, waterVis);
			hyPipe.PressDynamic = waterDensity * Math.Pow(hyPipe.Speed, 2.0) / 2.0;
			hyPipe.DragForce = hyPipe.PressDynamic * hyPipe.Length;
			if (beCircle)
			{
				hyPipe.Diameter = 20;
			}
			hyPipe.ResistanceLocal = hyPipe.PressDynamic * hyPipe.ResCoefLocal;
			hyPipe.Resistance = hyPipe.DragForce + hyPipe.ResistanceLocal;
		}

		public InBuildSystem BuildSystem
		{
			get
			{
				return this.buildSystem;
			}
			set
			{
				this.buildSystem = value;
			}
		}

		public int IndexLg
		{
			get
			{
				return this.index_lg;
			}
			set
			{
				this.index_lg = value;
			}
		}

		public int IndexLc
		{
			get
			{
				return this.index_lc;
			}
			set
			{
				this.index_lc = value;
			}
		}

		public int IndexHn
		{
			get
			{
				return this.index_hn;
			}
			set
			{
				this.index_hn = value;
			}
		}

		public int IndexHl
		{
			get
			{
				return this.index_hl;
			}
			set
			{
				this.index_hl = value;
			}
		}

		private OptionData option;

		private InBuildSystem buildSystem;

		private double averageTemper;

		private const double Roughness = 0.2;

		private const double AverageRm = 45.0;

		private bool beFirst = true;

		private double waterVis;

		private double waterDensity;

		private double densitySupply;

		private double densityReturn;

		private int index_lg;

		private int index_lc;

		private int index_hn;

		private int index_hl;
	}
}
